package org.styx.seata.tcc.account.tcc.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.styx.common.utils.ResultHolder;
import org.styx.seata.tcc.account.domain.Account;
import org.styx.seata.tcc.account.mapper.AccountMapper;
import org.styx.seata.tcc.account.tcc.AccountTccAction;

import java.math.BigDecimal;

/**
 * @date 2021/10/9
 * @auther uranus
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class AccountTccActionImpl implements AccountTccAction {
    private final AccountMapper accountMapper;

    @Transactional
    @Override
    public boolean prepareDecreaseAccount(BusinessActionContext context, Long userId, BigDecimal money) {
        log.info("扣减金额第一阶段，开始执行冻结金额操作！");
        Account account=
                accountMapper.selectOne(new LambdaQueryWrapper<Account>().eq(Account::getUserId,userId));
        if(account.getResidue().compareTo(money)<0){
            throw new RuntimeException("可用金额不足，金额冻结失败");
        }
        //执行冻结操作
        accountMapper.updateFrozen(userId,
                account.getResidue().subtract(money),
                account.getFrozen().add(money));

        //TODO 模拟异常
        if(Math.random()<0.5){
            throw new RuntimeException("模拟异常");
        }
        //创建标识
        ResultHolder.setResult(getClass(),context.getXid(),"p");
        log.info("扣减金额第一阶段，执行冻结金额完成");
        return false;
    }
    @Transactional
    @Override
    public boolean commit(BusinessActionContext context) {
        log.info("扣减金额第二阶段，开始执行提交操作");
        if(ResultHolder.getResult(getClass(),context.getXid())==null){
            return true;
        }
        Long userId=
                Long.parseLong(context.getActionContext("userId").toString());
        BigDecimal money=
                new BigDecimal(context.getActionContext("money").toString());

        accountMapper.updateFrozenToUsed(userId,money);
        ResultHolder.removeResult(getClass(),context.getXid());
        return false;
    }
    @Transactional
    @Override
    public boolean rollback(BusinessActionContext context) {
        log.info("扣减金额第二阶段，开始执行回滚操作");
        if(ResultHolder.getResult(getClass(),context.getXid())==null){
            return true;
        }
        Long userId=
                Long.parseLong(context.getActionContext("userId").toString());
        BigDecimal money=
                new BigDecimal(context.getActionContext("money").toString());

        accountMapper.updateFrozenToResidue(userId,money);

        ResultHolder.removeResult(getClass(),context.getXid());

        log.info("扣减金额第二阶段 ，执行回滚操作完成");
        return false;
    }
}
